package com.sms.test.intercept;

import com.sms.test.annotation.IPFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * @author Sen
 * @Date 2023/1/31
 * 对拦截到的请求进行判断是否刷单
 */
@Component
public class MyInterceptor implements HandlerInterceptor {

    @Autowired
    StringRedisTemplate redisTemplate;

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final Integer NUM_LIMIT = 3;//次数限制

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            IPFilter ipFilter = handlerMethod.getMethodAnnotation(IPFilter.class);//获取方法注解

            //对标有@IPFilter注解的方法进行过滤
            if(ipFilter !=null){
                String ip = request.getRemoteHost();//获取IP
                String time = LocalDateTime.now().format(DATE_TIME_FORMATTER);
                String key = ip + ":" + time;//组装key

                //判断是否是黑名单的ip
                if(redisTemplate.opsForSet().isMember("ipInBlack",ip)){
                    failResp(response);
                    return false;
                }
                //不是黑名单ip则根据key记录请求次数
                Long number = redisTemplate.opsForValue().increment(key);
                redisTemplate.expire(key,5, TimeUnit.DAYS);
                //请求次数超过限制则加入黑名单
                if(number >= NUM_LIMIT){
                    redisTemplate.opsForSet().add("ipInBlack",ip);
                    failResp(response);
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 响应信息
     * @param response
     */
    private void failResp(HttpServletResponse response) {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.print("当前IP请求次数过多，请稍后尝试");
            response.flushBuffer();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
